package parser.consulta;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import FilesManagers.CantOpenFileException;
import FilesManagers.FileManager;
import FilesManagers.NoMoreLinesException;
import parser.ComparadorUrls;
import parser.simbolo.delimitador.*;
import parser.simbolo.operador.*;
import structuresManagers.AbstractManager;

public class ConsultaCompuesta extends Consulta {

	private Consulta consulta1;
	private Consulta consulta2;
	private Operador operador;
	private int posicionOperador;
	private List<Operador>operadoresExistentes;
	private String temp;
	

	//private String temp2="tempConsultas2";
	
	public ConsultaCompuesta(String destinoResultado, AbstractManager a,String archivo) {
		super(destinoResultado,a,archivo);
		// TODO Apéndice de constructor generado automáticamente
		operadoresExistentes = new ArrayList<Operador>();
		operadoresExistentes.add(new Or());
		operadoresExistentes.add(new And());
		operadoresExistentes.add(new Not());
		this.temp = destinoResultado;
		
	}
	
	public void agregarOperador(Operador op){
		this.operadoresExistentes.add(op);
	}

	@Override
	public void setStringConsulta(String stringConsulta) {
		
		super.setStringConsulta(stringConsulta);
		setOperador(this.getStringConsulta());
		String subConsulta1;
		if(operador==null){
			subConsulta1=stringConsulta.toString();
		}else if(operador.isNot()){
			subConsulta1=getPostOperador(super.getStringConsulta());	
		} else{
			subConsulta1=getPreOperador(super.getStringConsulta());
		}
		
		if(isSimple(subConsulta1)){
			consulta1 = new ConsultaSimple(temp,this.getEstructura(),this.getFileEstructura());
		}else{
			consulta1 = new ConsultaCompuesta(temp,this.getEstructura(),this.getFileEstructura());
			//hardcodeado para las pruebas-.---------------------
			if(subConsulta1.charAt(0)=='(' && subConsulta1.charAt(subConsulta1.length()-1)==')')
				subConsulta1 = subConsulta1.substring(1,subConsulta1.length()-1);
		}		
		
		consulta1.setStringConsulta(subConsulta1);
		String subConsulta2="a";
		if(operador==null){
			subConsulta2=subConsulta1;
			operador=new Or();
			this.operador.setComparador(new ComparadorUrls());
		}else if(operador.isNot()){
			subConsulta2="TODAS LAS URLS";	
		}else{
			subConsulta2=getPostOperador(super.getStringConsulta());
		}
		
		if(operador.isNot()){
			consulta2 = new ConsultaTodas(temp,this.getEstructura(),this.getFileEstructura());
		}else if(isSimple(subConsulta2)){
			consulta2 = new ConsultaSimple(temp,this.getEstructura(),this.getFileEstructura());
		}else{
			consulta2 = new ConsultaCompuesta(temp,this.getEstructura(),this.getFileEstructura());
			if(subConsulta2.charAt(0)=='(' && subConsulta2.charAt(subConsulta2.length()-1)==')')
				subConsulta2 = subConsulta2.substring(1,subConsulta2.length()-1);
				
		}
		
		consulta2.setStringConsulta(subConsulta2);
		//los 2 primeros parametros son los archivos con los que debe operar, el 3ro donde debe escribir el resultado.
		
		
	}
	
	@Override
	public String ejecutar() throws CantOpenFileException {
		
		this.consulta1.ejecutar();
		this.consulta2.ejecutar();
			
		try {
			FileManager fm = new FileManager();				
			String url;
			List<String> lista1 = new ArrayList<String>();
			List<String> lista2 = new ArrayList<String>();
			
			fm.cargarArchivo(this.consulta1.getFileResultado());
			while((url = fm.obtenerSiguienteLinea())!=null){
				lista1.add(url);
			}
			fm.cerrarArchivo();
			FileManager.borrar(this.consulta1.getFileResultado());
			
			fm.cargarArchivo(this.consulta2.getFileResultado());
			while((url = fm.obtenerSiguienteLinea())!=null){
				lista2.add(url);
			}
			fm.cerrarArchivo();
			FileManager.borrar(this.consulta2.getFileResultado());
			
			lista1 = operador.operar(lista1,lista2);
			Iterator it = lista1.iterator();
			FileManager.borrar(this.getFileResultado());
			if(!it.hasNext())FileManager.append(this.getFileResultado(),"\n");
			while(it.hasNext()){
				FileManager.append(this.getFileResultado(),it.next()+"\n");
			}
			
			
			
			
		} catch (CantOpenFileException e) {
			// TODO Bloque catch generado automáticamente
			e.printStackTrace();
		} catch (NoMoreLinesException e) {
			// TODO Bloque catch generado automáticamente
			e.printStackTrace();
		}
		return this.getFileResultado();
		
	}

	
	

	private String getPreOperador(String consulta) {
		
		int hasta=0;
		if(this.posicionOperador>0) hasta = this.posicionOperador-1;
		 return (consulta.substring(0, hasta).trim());
		
	}

	private String getPostOperador(String consulta) {
		
		return consulta.substring(this.posicionOperador+this.operador.getSimbolo().length()).trim();
	}

	private void setOperador(String consulta) {
		Iterator<Operador> it = this.operadoresExistentes.iterator();
		Delimitador p1 = new Parentesis1();
		Delimitador p2 = new Parentesis2();
		while(it.hasNext()){
			Operador op= it.next();
			int pos=0;		
			int cantAntesAbiertos=0;
			int cantAntesCerrados=0;
			
			String consultaTemp = consulta;
			int nuevaPos=0;
			int viejaPos=0;
			while((pos=consultaTemp.indexOf(op.getSimbolo()))!=-1){
				
				//pos=nuevaPos+viejaPos;
				nuevaPos = pos+viejaPos;
				if(pos!=0){
					cantAntesAbiertos+=this.cantidadSeparadores(p1, consultaTemp.substring(0, pos-1));
					cantAntesCerrados+=this.cantidadSeparadores(p2, consultaTemp.substring(0, pos-1));
				}
				int cantDespuesAbiertos=this.cantidadSeparadores(p1, consultaTemp.substring(pos+op.getSimbolo().length()));
				int cantDespuesCerrados=this.cantidadSeparadores(p2, consultaTemp.substring(pos+op.getSimbolo().length()));
				//if(cantAntesAbiertos-cantAntesCerrados == cantDespuesCerrados - cantDespuesAbiertos){
				if(cantAntesAbiertos==cantAntesCerrados && cantDespuesCerrados == cantDespuesAbiertos){
					this.operador=op;
					this.posicionOperador=nuevaPos;
					this.operador.setComparador(new ComparadorUrls());
					//System.out.println("El operador era"+op.getSimbolo()+" en la pos"+nuevaPos);
					return;
				}else{
					int largo=consultaTemp.length();
					consultaTemp=consultaTemp.substring(pos+op.getSimbolo().length());
					
					viejaPos=largo-consultaTemp.length();
					//System.out.println("A: "+consultaTemp);
					int cantAbiertos=this.cantidadSeparadores(p1, consultaTemp);
					int cantCerrados=this.cantidadSeparadores(p2, consultaTemp);
					if(cantAbiertos != cantCerrados){
						int aux = consultaTemp.indexOf(p2.getSimbolo());
						
						cantAntesAbiertos=0;
						cantAntesCerrados=0;
						consultaTemp=consultaTemp.substring(aux+p2.getSimbolo().length());
						viejaPos=largo-consultaTemp.length();
						//System.out.println("B: "+consultaTemp);
					}
					
				}
				
			}
			
			
		}
		
		this.operador=null; //Debe crear el operador principal de la consulta
	}
	/**
	 * Supone delimitadores de un caracter.
	 * Devuelve la cantidad de apariciones en la linea
	 * */
	private int cantidadSeparadores(Delimitador s,String linea){
		int acum=0;
		for(int i=0; i<linea.length();i++){
			if(linea.charAt(i)==s.getAbreviado()){
				acum++;
			}
		}
		
		return acum;
	}
	
	private boolean isSimple(String consulta) {
		Iterator<Operador> it = this.operadoresExistentes.iterator();
		while(it.hasNext()){
			if(consulta.indexOf(it.next().getSimbolo())!=-1) return false;
			
		}
		return true;
	}
	private void cargarLista(String origen,List<String> lista) throws CantOpenFileException{
		FileManager f = new FileManager();
		f.cargarArchivo(origen);
		try {
			String linea;
			while((linea = f.obtenerSiguienteLinea())!=null){
				lista.add(linea);
				
			}
		} catch (NoMoreLinesException e) {
			// TODO Bloque catch generado automáticamente
			//e.printStackTrace();
		}
	}

}